﻿using Furion;
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.Core;
using Furion.Core.Entities.Enums;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Security.Claims;
using Furion.DatabaseAccessor.Extensions;
using System.Drawing;

using Furion.DistributedIDGenerator;
using Microsoft.Extensions.Caching.Memory;

namespace Furion.Application
{

    [AppAuthorize, ApiDescriptionSettings("System", Name = "Role", Order = 4, Tag = "角色")]
    public class RoleService : IDynamicApiController
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<Role> _roleRepository;
        private readonly IRepository<RolePermission> _rolePermissionRepository;
        private readonly IAuthorizationManager _authorizationManager;

        /// <summary>
        /// 缓存
        /// </summary>
        private readonly IMemoryCache _memoryCache;

        public RoleService(IHttpContextAccessor httpContextAccessor,
            IRepository<Role> roleRepository,
            IRepository<RolePermission> rolePermissionRepository,
            IAuthorizationManager authorizationManager,
            IMemoryCache memoryCache)
        {
            _httpContextAccessor = httpContextAccessor;
            _roleRepository = roleRepository;
            _rolePermissionRepository = rolePermissionRepository;
            _authorizationManager = authorizationManager;
            _memoryCache = memoryCache;
        }



        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_Add), HttpPost("/Role/Add"), ApiDescriptionSettings(Name = "Add")]
        public async Task AddAsync([Required] RoleAddInput input)
        {
            var addInput = input.Adapt<Role>();
            addInput.CreatedTime = DateTime.Now;
            addInput.UpdatedTime = DateTime.Now;
            addInput.CreatedUserId = _authorizationManager.UserId;

            int maxId = _roleRepository.DetachedEntities.Where(a => a.Id < 99).Max(a => a.Id);
            addInput.Id = maxId+1;

            var entryEntity = await _roleRepository.InsertNowAsync(addInput);
        }


        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_Edit), HttpPost("/Role/Edit"), ApiDescriptionSettings(Name = "Edit")]
        public async Task EditAsync([Required] RoleEditInput input)
        {
            var editInput = input.Adapt<Role>();
            editInput.UpdatedTime = DateTime.Now;
            editInput.UpdatedUserId = _authorizationManager.UserId;

            

            await _roleRepository.UpdateAsync(editInput);
        }



        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_List), HttpGet("/Role/PageList"), ApiDescriptionSettings(Name = "PageList")]
        public async Task<PagedList<RoleOutPut>> PageListAsync([FromQuery] RoleSearchPageInput input)
        {
            var hasKeyword = !string.IsNullOrEmpty(input.Keyword?.Trim());

            var list = await _roleRepository.Include(a=>a.Permissions)
                .Where(hasKeyword, a => a.Name.Contains(input.Keyword.Trim()) )
                .OrderBy(a => a.Id)
                .ToPagedListAsync(input.PageIndex, input.PageSize);

            return list.Adapt<PagedList<RoleOutPut>>(); ;
        }


        /// <summary>
        /// 列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_List),HttpGet("/Role/List"), ApiDescriptionSettings(Name = "List")]
        public async Task<dynamic> ListAsync([FromQuery] RoleSearchInput input)
        {
            var hasKeyword = !string.IsNullOrEmpty(input.Keyword?.Trim());

            var list = await _roleRepository.DetachedEntities
                .Where(a => a.IsDeleted == false)
                .Where(a=>a.Enabled==input.Enabled)
                .Where(hasKeyword, a =>  a.Name.Contains(input.Keyword.Trim()))
                .OrderBy(a => a.Id)
                .Select(a=>new { 
                 a.Id,
                 a.Name
                })
                .ToListAsync();

            return list;
        }


        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_Delete),HttpPost("/Role/Delete"), ApiDescriptionSettings(Name = "Delete")]
        public async Task DeleteRange(RoleDeleteRangeInput input)
        {
            string DefaultAppRoleId = App.Configuration["AppInfo:DefaultAppRoleId"].ToString();
            if (input.Ids.Contains(Convert.ToInt32(DefaultAppRoleId)))
            {
                throw Oops.Oh("内置角色禁止删除");
            }

            var items = await _roleRepository.DetachedEntities.Where(u => input.Ids.Contains(u.Id)).ToListAsync();
            if(items.Count>0)
            {
                await _roleRepository.DeleteNowAsync(items);
            }            
        }

        /// <summary>
        /// 设置权限
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.Role_Permission),HttpPost("/Role/SetRolePermission"), ApiDescriptionSettings(Name = "SetRolePermission")]
        public async Task SetRolePermission([Required] RolePermissionInput input)
        {
            if(input.RoleId>0 && input.PermissionIds.Length>0)
            {
                var items = await _rolePermissionRepository.DetachedEntities.Where(a => a.RoleId == input.RoleId).ToListAsync();
                if (items.Count>0)
                {
                    await _rolePermissionRepository.DeleteNowAsync(items);
                }

                var list = new List<RolePermission>();
                foreach (var id in input.PermissionIds)
                {
                    list.Add(new RolePermission { RoleId = input.RoleId, PermissionId = id });
                }
                await _rolePermissionRepository.InsertNowAsync(list);
            }
            else
            {
                throw Oops.Oh("参数错误");
            }
        }
    }
}
